#include "uid_key_flash.h"

#if DEBUG
#include "usart.h"
#endif

uid_4byte card4_id;
key_6byte buf_key;
/**
 * @brief Format_Buf(void)擦除缓冲flash区
 * @param  : 
 * @param  :
 * @retval 返回状态，详情参考key_enum
 */

key_enum Format_Buf()
{
	fmc_unlock();
	if(fmc_page_erase(FLASH_BUFFER_START_ADDRESS) != FMC_READY)
	{
		return FORMAT_ERR;
	}
	fmc_lock();
	return FORMAT_OK;
}


/**
 * @brief Flash_ConWrite连续写n个32位数据 ，地址必须位偶数
 * @param  address:存入地址
 * @param  data:数据
 * @param  size:数据大小
 * @retval 返回状态，详情参考key_enum
 */
key_enum Flash_ConWrite(uint32_t address,uint32_t *data,uint16_t size)
{
	uint16_t i;
	fmc_unlock();
	for(i=0;i<size;i++)
	{
		if(fmc_word_program(address+i*4,data[i])!= FMC_READY)
		{
			return WRITE_ERR;
		}
	}
	fmc_lock();
	return WRITE_OK;
}

/**
 * @brief Flash_BufferWrite 将一片区数据存入另一片区
 * @param  address:存入的目的地址
 * @param  size:数据大小字节单位,最大不超过一片区，超过的数据会被舍弃
 * @param  data_address:存入数据的地址
 * @retval 返回状态，详情参考key_enum
 */
key_enum Flash_BufferWrite(uint32_t address,uint16_t size,
uint32_t data_address)
{
	uint16_t i;
	uint32_t buf;
	uint8_t re,temp;
	fmc_unlock();	
	
	for(i=0;i<size/4;i++)
	{

		read_4bytebuf(data_address+i*4,&buf,1);
		if(fmc_word_program((address+i*4),buf) != FMC_READY)
		{
			return WRITE_ERR;
		}
	}
	re = size%4;
	if(re != 0)
	{

		read_4bytebuf(data_address+i*4,&buf,1);
		temp = 4-re;
		for(re=0;re<temp;re++)
		{
			buf |= (0xFF<<(24-re*8));
		}
		if(fmc_word_program((address+i*4),buf) != FMC_READY)
		{
			return WRITE_ERR;
		}
	}
	fmc_lock();
	return FLASH_OK;
}


/**
 * @brief Flasg_UID_Write 增加减少uid
 * @param  com:增加或者减少 1增加 0减少
 * @param  cln:uid的级联
 * @param  address:增加的首地址或者是减少的首地址
 * @param  data:增加的uid
 * @param  size:该片区uid数量
 * @param  block_address:存放该uid的片区首地址
 * @retval 返回状态，详情参考key_enum
 */
key_enum Flash_UID_Write(uint8_t com,uint8_t cln,uint32_t address
,uint32_t *data,uint16_t size,uint32_t block_address)
{
	uint8_t temp,temp_p;
	if(size == BLOCK_UID_SIZE)return WRITE_ERR;
	if(Format_Buf() != FORMAT_OK)return FORMAT_ERR;//清空缓冲区
	temp = 4;
	temp_p = 22;
	//将片区数据送入缓冲片区
	if(Flash_BufferWrite(FLASH_BUFFER_START_ADDRESS+2
		,temp_p+(size*temp),block_address+2) != FLASH_OK)
	{
		return WRITE_ERR;
	}
	//清除原本数据
	fmc_unlock();
	fmc_page_erase(block_address);
	//增加
	if(com == 1)
	{
		//重新写入uid数量
		size++;
		while(1)
		{
			if(fmc_halfword_program(block_address,size) == FMC_READY)
			{
				break;
			}
		}
		fmc_lock();
		//将缓冲区的备份写入到片区
		while(1)
		{
			if(Flash_BufferWrite(block_address+2,temp_p+((size-1)*temp)
				,FLASH_BUFFER_START_ADDRESS+2) == FLASH_OK)
			{
				break;
			}
		}
		//写入新的uid
		if(Flash_ConWrite(address,data,1) != WRITE_OK)
		{
			return WRITE_ERR;
		}
	}
	//减少
	else if(com == 0)
	{
		//重新写入uid数量
		if(size>0)
		{
			size--;
		}
		else
		{
			return CARD_ERR;
		}
		while(1)
		{
			//写入2字节数据长度
			if(fmc_halfword_program(block_address,size) == FMC_READY)
			{
				break;
			}
		}
		
		fmc_lock();
		//将缓冲区的第一部分备份写入到片区
		while(1)
		{
			/*
			block_address+2 块地址+2 
			(address-block_address-2) uid块地址-首地址再减数据长度
			FLASH_BUFFER_START_ADDRESS+2 缓冲区的地址+2
			将uid之前的数据写入
			*/
			if(Flash_BufferWrite(block_address+2,
				(uint16_t)(address-block_address-2)
				,FLASH_BUFFER_START_ADDRESS+2) == FLASH_OK)
			{
				break;
			}
		}
		//第二部分数据
		while(1)
		{
			/*
			address uid首地址
			((size)*temp+temp_p)-(address-block_address)  （uid-1）长度+22 - (uid首地址-块地址)
			(FLASH_BUFFER_START_ADDRESS)+(address-block_address)+4  缓冲区跳过删去uid的地址
			*/
			
			if(Flash_BufferWrite(address,
				(uint16_t)((size)*temp+temp_p)-(address-block_address)
				,(FLASH_BUFFER_START_ADDRESS)+(address-block_address)+4)
				== FLASH_OK)
			{
				break;
			}
		}
	}
	return FLASH_OK;
}





/**
 * @brief Format_moudle 初始化moudle 初始化成初始密码123456
 * @param  : 无
 * @param  :无
 * @retval 返回状态，详情参考key_enum
 */
key_enum Format_moudle(void)
{
	uint32_t i;
	fmc_unlock();//开锁
	for(i=UID_4BYTE_FIRST;i<FLASH_ADDRESS_END;i+=BLOCK_SIZE)
	{
		if(fmc_page_erase(i) != FMC_READY)
		{
			return FORMAT_ERR;
		}
	}
	//初始化管理员密码333333
	fmc_word_program(ADMIN_KEY,0x03030303);
	fmc_halfword_program(ADMIN_KEY+4,0x0303);
	//初始化用户密码666666
	fmc_word_program(USER_KEY,0x06060606);
	fmc_halfword_program(USER_KEY+4,0x0606);
	
	fmc_halfword_program(UID_4BYTE_FIRST,0);
	fmc_halfword_program(UID_4BYTE_FIRST+BLOCK_SIZE,0);
	fmc_halfword_program(UID_4BYTE_FIRST+2*BLOCK_SIZE,0);
	fmc_halfword_program(UID_4BYTE_FIRST+3*BLOCK_SIZE,0);
	fmc_lock();
	return FORMAT_OK;
}

/**
 * @brief Flash_Changekey 更改密码
 * @param  com:1为修改用户密钥，0为修改管理员密钥
 * @param  key_6byte: 新密钥数据
 * @retval 
 */
void Flash_Changekey(uint8_t com , key_6byte *buf)
{
	Format_Buf();

	uint32_t uid_num;
	read_4bytebuf(UID_4BYTE_FIRST,&uid_num,1);
	uint32_t size = uid_num*4+22;
	Flash_BufferWrite(FLASH_BUFFER_START_ADDRESS,size,UID_4BYTE_FIRST);
	fmc_unlock();
	fmc_page_erase(UID_4BYTE_FIRST);
	fmc_lock();
	//1
	if(com)
	{
		size = 16;
	}
	//0
	else
	{
		size = 10;
	}
	Flash_BufferWrite(UID_4BYTE_FIRST,size,FLASH_BUFFER_START_ADDRESS);
	fmc_unlock();
	fmc_halfword_program(UID_4BYTE_FIRST+size,buf->key_buf[0]);
	size+=2;
	fmc_halfword_program(UID_4BYTE_FIRST+size,buf->key_buf[1]);
	size+=2;
	fmc_halfword_program(UID_4BYTE_FIRST+size,buf->key_buf[2]);
	size+=2;
	fmc_lock();
	Flash_BufferWrite(UID_4BYTE_FIRST+size,(uid_num*4+22-size),FLASH_BUFFER_START_ADDRESS+size);
}

/**
 * @brief read_4bytebuf 以4字节为单位读flash。
		  因为stm32f030读flash时uint32_t 读取数据地址必须为四的偶数，
			该函数则不需要
 * @param  address: 读取的首地址
 * @param  buf:存放数据的数组
 * @param  length:读取的长度
 * @retval 
 */
void read_4bytebuf(uint32_t address,uint32_t *buf,uint16_t length)
{
	uint16_t i;
	uint8_t temp=0,j;
	uint32_t t;
	for(i=0;i<length;i++)
	{
		buf[i] = 0;
		for(j=0;j<4;j++)
		{
			temp = *(uint8_t*)(address+(i*4)+j);
			t = temp << (8*j);
			buf[i] |= t;
		}
	}
}

/**
 * @brief read_2bytebuf 以2字节为单位读flash
 * @param  address: 读取的首地址
 * @param  buf:存放数据的数组
 * @param  length:读取的长度
 * @retval 
 */
void read_2bytebuf(uint32_t address,uint16_t *buf,uint16_t length)
{
	uint16_t i;
	uint8_t temp=0,j;
	uint16_t t;
	for(i=0;i<length;i++)
	{
		buf[i] = 0;
		for(j=0;j<2;j++)
		{
			temp = *(uint8_t*)(address+(i*4)+j);
			t = temp << (8*j);
			buf[i] |= t;
		}
	}
}



/**
 * @brief IsaddOrsub 判断是否为add，subui
 * @param  cln: 级联标志
 * @param  uid:uid数据
 * @retval 1为增加，2为减少，0不为管理uid
 */
uint8_t IsaddOrsub(uint8_t cln,uint8_t *uid)
{
	

		read_4bytebuf(UID_4BYTE_ADDCARD_UID,&card4_id.uid_buf,1);
		if(memcmp(card4_id.uid_byte,&uid[1],4)==0)
		{
			return 1;
		}
		read_4bytebuf(UID_4BYTE_SUBCARD_UID,&card4_id.uid_buf,1);
		if(memcmp(card4_id.uid_byte,&uid[1],4)==0)
		{
			return 2;
		}
	
	return 0;
}

/**
 * @brief Compare_4UID比较uid
 * @param  uid: 读取的uid uid[0]舍弃 从1开始
 * @param  index:若uid存在，返回uid的索引
 * @param  block_num:若uid存在，返回uid所在的片区号
 * @retval 0 uid不存在flash中
 */
uint8_t Compare_4UID(uint8_t *uid,uint16_t *index,uint8_t *block_num)
{
	uint16_t i,length;
	uint8_t j=0;
	*index = 0;
	*block_num = 0;
	while(1)
	{
		read_2bytebuf(UID_4BYTE_FIRST+j*BLOCK_SIZE,&length,1);
		if(length <=0 )
		{
			return 0;
		}
		for(i=0;i<length;i++)
		{
			read_4bytebuf(UID_4DATA_ADDRESS+i*4+j*BLOCK_SIZE,&card4_id.uid_buf,1);
			if(0 == memcmp(card4_id.uid_byte,&uid[1],4))
			{
				*index = i;
				*block_num = j;
				return 1;
			}
			#if DEBUG
			else
			{
				uid_4byte x;
				x.uid_byte[0] = uid[0];
				x.uid_byte[1] = uid[0];
				x.uid_byte[2] = uid[0];
				x.uid_byte[3] = uid[0];
				printf("flash = %08x\r\n",card4_id.uid_buf);
				printf("block_num = %d\r\n",j);
				printf("uid_num = %d",i);
			}
			
			#endif
		}
		j++;
		if(j>(UID_FLASH_SIZE/BLOCK_SIZE))
		{
			return 0;
		}
	}
}


/**
 * @brief Change_AdminUid修该uid
 * @param  cln: 级联
 * @param  uid:输入的uid数据
 * @param  com:1修改add功能0修改sub
 * @retval 
 */
void Change_AdminUid(uint8_t cln,uint8_t *uid,uint8_t com)
{
	uid_4byte id;
	uint32_t b_address;
	uint8_t temp,len,s;

		memcpy(id.uid_byte,&uid[1],4);
		b_address = UID_4BYTE_FIRST;
		len = 22;
		s = 4;
		if(com == 1)
		{
			temp = 2;
		}
		else
		{
			temp = 6;
		}

	//清空缓冲区
	Format_Buf();

	uint16_t size;
	read_2bytebuf(b_address,&size,1);
	size = len+size*s;
	Flash_BufferWrite(FLASH_BUFFER_START_ADDRESS,size,b_address);
	
	//清楚原本数据
	fmc_unlock();
	fmc_page_erase(b_address);
	fmc_lock();
	
	//将第一部分数据写入
	Flash_BufferWrite(b_address,temp,FLASH_BUFFER_START_ADDRESS);
	//将修改的数据写入
	Flash_ConWrite(b_address+temp,&id.uid_buf,1);
	//将第二部分数据写入
	Flash_BufferWrite(b_address+temp+s,(size-temp-s),FLASH_BUFFER_START_ADDRESS+temp+s);
}


/**
 * @brief format_card清空所有uid
 * @retval 
 */
void format_card(void)
{
	uint16_t length;
	uint8_t i,j;
	uint16_t buf[11];
	for(i=0;i<2;i++)
	{

		read_2bytebuf(UID_4BYTE_FIRST+i*BLOCK_SIZE,&length,1);
		if(length != 0)
		{
			for(j=0;j<11;j++)
			{

				read_2bytebuf(UID_4BYTE_FIRST+i*BLOCK_SIZE+j*2,&buf[j],1);
			}
			buf[0] = 0;
			fmc_unlock();
			fmc_page_erase(UID_4BYTE_FIRST+i*BLOCK_SIZE);
			for(j=0;j<11;j++)
			{
				fmc_halfword_program((UID_4BYTE_FIRST+i*BLOCK_SIZE+j*2),buf[j]);
			}
			fmc_lock();
		}
	}
}

void flash_init(void)
{
	FLASH_SetLatency(FLASH_Latency_1);
	FLASH_PrefetchBufferCmd(ENABLE);
}

/**
 * @brief 获取用户和管理员密钥
 * @param  admin_key: 存放管理员密钥的数组地址
 * @param  user_key:存放用户密钥的数组地址
 * @retval 
 */
void getkey(key_6byte *admin_key,key_6byte *user_key)
{
	uint8_t i;
	for(i=0;i<3;i++)
	{
		read_2bytebuf(ADMIN_KEY+i*2,&(admin_key->key_buf[i]),1);
	}
	for(i=0;i<3;i++)
	{

		read_2bytebuf(USER_KEY+i*2,&(user_key->key_buf[i]),1);
	}
}
